<?php
/**
 * リクエストクラス定義ファイル
 *
 * リクエスト基底クラス及びHTTPリクエストクラスが含まれています
 */

/**
 * リクエスト基底クラス
 *
 */
abstract class Request {

	/**
	 * プロセス名
	 *
	 * @var string
	 */
	public $proc = '';

	/**
	 * アクション名
	 *
	 * @var string
	 */
	public $act = '';

	/**
	 * XML出力が要求されているかどうか
	 *
	 * @var string
	 */
	public $xmlMode = '';

	/**
	 * catchAllメソッド
	 *
	 * ビューから届けられるデータをバリューオブジェクトにマップする
	 *
	 * @param SimpleXMLElement $valueObject 格納先バリューオブジェクト
	 */
	abstract function catchAll(SimpleXMLElement $valueObject);
}

/**
 * HTTPリクエストクラス
 *
 * ブラウザ等から受け取ったデータをXMLツリーとして構成する
 *
 */
class HTTPRequest extends Request {
	/**
	 * ブラウザから送出されるリクエストデータを解析しバリューオブジェクトへ格納
	 *
	 * $_REQUESTに含まれるデータをXMLに変換し
	 * 各リクエストに内包されるアクション、タイプ各コマンドを分離
	 *
	 * @param SimpleXMLElement $valueObject 格納先バリューオブジェクト
	 */
	public function catchAll(SimpleXMLElement $valueObject) {
		$this->buildTree($valueObject);
		$this->splitCommand();
	}

	/**
	 * $_REQUEST及び$_FILESからのデータをXML要素に変換する
	 *
	 * $formElemを親要素として
	 * <フィールド名>
	 *     <value>データ</value>
	 * </フィールド名>
	 * という子要素を追加する
	 * データが配列の場合は
	 * <フィールド名 dataType="array">
	 *     <value>データ1</value>
	 *     <value>データ2</value>
	 * </フィールド名>
	 * という形になる
	 *
	 * @param SimpleXmlElement $targetElem 対象要素
	 */
	private function buildTree(SimpleXMLElement $targetElem) {
		// $_REQUESTを処理
		foreach($_REQUEST as $key => $val) {
			$keyElem = $targetElem->addChild($key);
			if (is_array($val)) {
				$keyElem->addAttribute('dataType','array');
				foreach($val as $dat) {
					$keyElem->addChild('value',htmlentities(stripslashes($dat),ENT_QUOTES,'UTF-8'));
				}
			} else {
				$keyElem->addChild('value',htmlentities(stripslashes($val),ENT_QUOTES,'UTF-8'));
			}
		}
		// $_FILESを処理
		if (is_array($_FILES)) {
			foreach($_FILES as $key => $val) {
				if ($val['size'] > 0) {
					$keyElem = $targetElem->addChild($key);
					$keyElem->addAttribute('dataType','file');
					$keyElem->addChild('value',htmlentities(stripslashes($val['name']),ENT_QUOTES,'UTF-8'));
					$keyElem->addChild('mimetype',$val['type']);
					$keyElem->addChild('filesize',$val['size']);
					$keyElem->addChild('tmpfile',$val['tmp_name']);
					$keyElem->addChild('uploaderr',$val['error']);
				}
			}
		}
	}

	/**
	 * ディスパッチャー
	 *
	 * @param string $dispatchConfigFile ディスパッチルールファイル名
	 */
	private function dispatchCommand($dispatchConfigFile) {
		$dispatch = simplexml_load_file(VISION_APP_PATH.'settings/'.$dispatchConfigFile);
		$uri = relative_uri();
		$rules = $dispatch->xpath("//rule[@mode='URI'][@param='$uri']");
		if ($rules) {
			foreach($rules as $rule) {
				if ($rule->proc) {
					$this->proc = (string) $rule->proc;
				}
				if ($rule->act) {
					$this->act = (string) $rule->act;
				}
			}
		}
	}

	/**
	 * リクエストデータから要求されている処理と動作を抽出する
	 *
	 * POSTまたはGETメソッドで渡されるプロセス名(vp)、アクション名(va)を
	 * 取得する
	 *
	 */
	private function splitCommand() {
		if (isset($_REQUEST['vp'])) {
			$this->proc = trim($_REQUEST['vp']);
		}
		if (isset($_REQUEST['va'])) {
			$this->act = trim($_REQUEST['va']);
		}
		if (isset($_REQUEST['vx'])) {
			$this->xmlMode = trim($_REQUEST['vx']);
		}
		// ディスパッチャーが有効であれば
		if (Vision::$setting->dispatcher['enable'] == 'true') {
			$this->dispatchCommand(Vision::$setting->dispatcher->config);
		}
	}
}
